home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- *
- * NSSDC/CDF Virtual STREAM_LF.
- *
- * Version 4.0, 2-Mar-92, ST Systems (STX)
- *
- * Modification history:
- *
- * V1.0 22-Jan-91, J Love Original version (developed for CDF V2.0).
- * V2.0 12-Mar-91, J Love All fixes to V1.x. Modified vread and vwrite
- * to buffer only when necessary.
- * V3.0 14-May-91, J Love Added caching (for CDF V2.1).
- * V3.1 31-Jul-91, J Love Added veof. Added 'memmove' for UNIX. Added
- * "deq - default extension quantity" if VMS.
- * Changed algorithm that looks for bufferN.
- * Added number of CACHE buffers as a parameter
- * specified in 'Vopen'. Renamed functions to
- * avoid collisions on SGi/IRIX.
- * V3.2 15-Aug-91, J Love Changed for IBM-PC/MS-DOS port.
- * V4.0 2-Mar-92, J Love IBM PC port/CDF V2.2.
- *
- ******************************************************************************/
-
- #include "vio.h"
-
- /******************************************************************************
- * Local function prototypes.
- ******************************************************************************/
-
- #if defined(vms) | defined(__MSDOS__)
- long EXTENDfile (VFILE *, long);
- long ALLOCbuffer (VFILE *, long *);
- #endif
-
- #if defined(unix)
- long EXTENDfile ();
- long ALLOCbuffer ();
- #endif
-
- /******************************************************************************
- * Read from the file.
- * WARNING: This macro has a 'return' statement.
- ******************************************************************************/
-
- #define READ(offset,buffer,itemsize,numitems,vfp,OnErrorReturn) { \
- int _try; \
- for (_try = 1; _try <= vioMAX_TRYs; _try++) { \
- if (fseek(vfp->fp,offset,SEEK_SET) == EOF) { \
- vfp->error = TRUE; \
- return OnErrorReturn; \
- } \
- if (fread(buffer,itemsize,numitems,vfp->fp) == numitems) break; \
- } \
- if (_try > vioMAX_TRYs) { \
- vfp->error = TRUE; \
- return OnErrorReturn; \
- } \
- }
-
- /******************************************************************************
- * Write to the file.
- * WARNING: This macro has a 'return' statement.
- ******************************************************************************/
-
- #define WRITE(offset,buffer,itemsize,numitems,vfp,OnErrorReturn) { \
- int _try; \
- for (_try = 1; _try <= vioMAX_TRYs; _try++) { \
- if (fseek(vfp->fp,offset,SEEK_SET) == EOF) { \
- vfp->error = TRUE; \
- return OnErrorReturn; \
- } \
- if (fwrite(buffer,itemsize,numitems,vfp->fp) == numitems) break; \
- } \
- if (_try > vioMAX_TRYs) { \
- vfp->error = TRUE; \
- return OnErrorReturn; \
- } \
- }
-
- /******************************************************************************
- * Free memory allocated for a file.
- ******************************************************************************/
-
- #define FREEvfp(vfp) { \
- long _bufferN; \
- if (vfp->CACHEblockN != NULL) free (vfp->CACHEblockN); \
- if (vfp->CACHEmodified != NULL) free (vfp->CACHEmodified); \
- if (vfp->CACHEaccessedAt != NULL) free (vfp->CACHEaccessedAt); \
- if (vfp->CACHEbuffers != NULL) { \
- for (_bufferN = 0; _bufferN < vfp->nCACHEbuffers; _bufferN++) \
- if (vfp->CACHEbuffers[_bufferN] != NULL) \
- free (vfp->CACHEbuffers[_bufferN]); \
- free (vfp->CACHEbuffers); \
- } \
- free (vfp); \
- }
-
- /******************************************************************************
- * Check if a block is in the cache.
- ******************************************************************************/
-
- #define CACHEbufferN(vfp,blockN,bufferN) { \
- long _bufferNt; \
- if (vfp->lastBufferNaccessed != -1) { \
- if (vfp->CACHEblockN[vfp->lastBufferNaccessed] == blockN) \
- bufferN = vfp->lastBufferNaccessed; \
- else { \
- bufferN = -1; \
- for (_bufferNt = 0; _bufferNt < vfp->nCACHEbuffers; _bufferNt++) { \
- if (vfp->CACHEblockN[_bufferNt] == -1) \
- break; \
- else \
- if (vfp->CACHEblockN[_bufferNt] == blockN) { \
- bufferN = _bufferNt; \
- break; \
- } \
- } \
- } \
- } \
- else \
- bufferN = -1; \
- }
-
- /******************************************************************************
- * Extend the file to a specified number of blocks.
- ******************************************************************************/
-
- static long EXTENDfile(vfp,toBlockN)
- VFILE *vfp;
- long toBlockN;
- {
- long Nbytes;
- long blockN;
- long bufferNt;
- void *buffer;
- Nbytes = vfp->PHYeof - nCACHE_BUFFER_BYTEs * vfp->PHYlastBlockN;
- if (Nbytes < nCACHE_BUFFER_BYTEs) {
- CACHEbufferN (vfp, vfp->PHYlastBlockN, bufferNt);
- if (bufferNt != -1) {
- WRITE ((nCACHE_BUFFER_BYTEs * vfp->PHYlastBlockN),
- vfp->CACHEbuffers[bufferNt], nCACHE_BUFFER_BYTEs, 1, vfp, 0);
- vfp->CACHEmodified[bufferNt] = FALSE;
- }
- else {
- buffer = (void *) calloc (nCACHE_BUFFER_BYTEs, 1);
- if (buffer == NULL) {
- vfp->error = TRUE;
- return 0;
- }
- READ ((nCACHE_BUFFER_BYTEs * vfp->PHYlastBlockN), buffer, Nbytes, 1, vfp,
- 0);
- WRITE ((nCACHE_BUFFER_BYTEs * vfp->PHYlastBlockN), buffer,
- nCACHE_BUFFER_BYTEs, 1, vfp, 0);
- free (buffer);
- }
- vfp->PHYeof = nCACHE_BUFFER_BYTEs * (vfp->PHYlastBlockN + 1);
- }
- buffer = NULL;
- for (blockN = vfp->PHYlastBlockN + 1; blockN <= toBlockN; blockN++) {
- CACHEbufferN (vfp, blockN, bufferNt);
- if (bufferNt != -1) {
- WRITE ((nCACHE_BUFFER_BYTEs * blockN), vfp->CACHEbuffers[bufferNt],
- nCACHE_BUFFER_BYTEs, 1, vfp, 0);
- vfp->CACHEmodified[bufferNt] = FALSE;
- }
- else {
- if (buffer == NULL) {
- buffer = (void *) calloc (nCACHE_BUFFER_BYTEs, 1);
- if (buffer == NULL) {
- vfp->error = TRUE;
- return 0;
- }
- }
- WRITE ((nCACHE_BUFFER_BYTEs * blockN), buffer, nCACHE_BUFFER_BYTEs, 1,
- vfp, 0);
- }
- vfp->PHYlastBlockN = blockN;
- vfp->PHYeof = nCACHE_BUFFER_BYTEs * (blockN + 1);
- }
- if (buffer != NULL) free (buffer);
- return 1;
- }
-
- /******************************************************************************
- * Allocate a cache buffer to use. It may be necessary to page out a block
- * to the file.
- ******************************************************************************/
-
- static long ALLOCbuffer(vfp,bufferN)
- VFILE *vfp;
- long *bufferN;
- {
- long bufferNt;
- long oldestAccessedAt;
- long Nbytes;
- long offset;
- long i;
-
- *bufferN = -1;
-
- /******************************************************************************
- * check if there are any unused CACHE buffers - if so, the buffer must be
- * allocated (MALLOCed)
- ******************************************************************************/
-
- for (bufferNt = 0; bufferNt < vfp->nCACHEbuffers; bufferNt++)
- if (vfp->CACHEblockN[bufferNt] == -1) {
- vfp->CACHEbuffers[bufferNt] = (char *) malloc (nCACHE_BUFFER_BYTEs);
- if (vfp->CACHEbuffers[bufferNt] == NULL) {
- vfp->error = TRUE;
- return 0;
- }
- *bufferN = bufferNt;
- break;
- }
-
- /******************************************************************************
- * if there were no unused buffers, check for the least-recently-used (LRU)
- * buffer that has not been modified
- ******************************************************************************/
-
- if (*bufferN == -1) {
- oldestAccessedAt = vfp->pseudoClock;
- for (bufferNt = 0; bufferNt < vfp->nCACHEbuffers; bufferNt++)
- if ( ! vfp->CACHEmodified[bufferNt])
- if (vfp->CACHEaccessedAt[bufferNt] < oldestAccessedAt) {
- *bufferN = bufferNt;
- oldestAccessedAt = vfp->CACHEaccessedAt[bufferNt];
- }
- }
-
- /******************************************************************************
- * if all buffers have been modified, determine the LRU
- ******************************************************************************/
-
- if (*bufferN == -1) {
- oldestAccessedAt = vfp->pseudoClock;
- for (bufferNt = 0; bufferNt < vfp->nCACHEbuffers; bufferNt++)
- if (vfp->CACHEaccessedAt[bufferNt] < oldestAccessedAt) {
- *bufferN = bufferNt;
- oldestAccessedAt = vfp->CACHEaccessedAt[bufferNt];
- }
- }
-
- /******************************************************************************
- * if the buffer choosen has been modified, write it out to the file
- ******************************************************************************/
-
- if (vfp->CACHEmodified[*bufferN]) {
- offset = nCACHE_BUFFER_BYTEs * vfp->CACHEblockN[*bufferN];
- if (offset > vfp->PHYeof)
- if (EXTENDfile (vfp, (vfp->CACHEblockN[*bufferN] - 1)) == 0) return 0;
- #if defined(vms)
- Nbytes = nCACHE_BUFFER_BYTEs;
- #endif
- #if defined(unix) | defined(__MSDOS__)
- Nbytes = Minimum (nCACHE_BUFFER_BYTEs, (vfp->eof - offset));
- #endif
- WRITE (offset, vfp->CACHEbuffers[*bufferN], Nbytes, 1, vfp, 0);
- vfp->CACHEmodified[*bufferN] = FALSE;
- vfp->PHYlastBlockN = Maximum (vfp->PHYlastBlockN,
- vfp->CACHEblockN[*bufferN]);
- vfp->PHYeof = Maximum (vfp->PHYeof,
- ((nCACHE_BUFFER_BYTEs * vfp->CACHEblockN[*bufferN])
- + Nbytes));
- }
-
- /******************************************************************************
- * setup the buffer for use
- ******************************************************************************/
-
- for (i = 0; i < nCACHE_BUFFER_BYTEs; i++) vfp->CACHEbuffers[*bufferN][i] = 0;
- vfp->CACHEblockN[*bufferN] = -1;
- vfp->CACHEaccessedAt[*bufferN] = -1;
-
- return 1;
- }
-
- /******************************************************************************
- * Page in a block from the file.
- ******************************************************************************/
-
- #define PAGEin(vfp,blockN,bufferN,OnErrorReturn) { \
- long _offset; \
- long _Nbytes; \
- if (ALLOCbuffer(vfp,&bufferN) == 0) return OnErrorReturn; \
- _offset = blockN * nCACHE_BUFFER_BYTEs; \
- _Nbytes = Minimum (nCACHE_BUFFER_BYTEs, (vfp->PHYeof - _offset)); \
- READ (_offset, vfp->CACHEbuffers[bufferN], _Nbytes, 1, vfp, OnErrorReturn); \
- vfp->CACHEblockN[bufferN] = blockN; \
- vfp->CACHEmodified[bufferN] = FALSE; \
- }
-
- /******************************************************************************
- * Write a block out to the file.
- ******************************************************************************/
-
- #define WRITEblock(vfp,blockN,buffer,Nbytes,OnErrorReturn) { \
- long _offset; \
- _offset = nCACHE_BUFFER_BYTEs * blockN; \
- if (_offset > vfp->PHYeof) \
- if (EXTENDfile (vfp, (blockN - 1)) == 0) return OnErrorReturn; \
- WRITE (_offset, buffer, Nbytes, 1, vfp, OnErrorReturn); \
- vfp->PHYlastBlockN = Maximum (vfp->PHYlastBlockN, blockN); \
- vfp->PHYeof = Maximum (vfp->PHYeof, (_offset + Nbytes)); \
- }
-
- /******************************************************************************
- * Vopen - open the file and setup V structure.
- ******************************************************************************/
-
- VFILE *Vopen (file_spec, a_mode, n_buffers)
- char *file_spec; /* file specification */
- char *a_mode; /* access mode */
- long n_buffers; /* number of CACHE buffers to use (0 means use the
- default number) */
- {
- VFILE *vfp; /* pointer to V structure */
- int status; /* status from I/O function call */
- long bufferN; /* cache buffer number */
-
- #if defined(vms)
- char mrs[10+1]; /* maximum record size */
- char deq[10+1]; /* default allocation quantity */
- #endif
-
- /******************************************************************************
- * allocate V structure (including CACHE buffers)
- ******************************************************************************/
-
- vfp = (VFILE *) calloc (1, sizeof(VFILE)); /* everything starts at 0 */
- if (vfp == NULL) return NULL;
-
- vfp->magic_number = VIO_MAGIC_NUMBER;
-
- if (n_buffers > 0)
- vfp->nCACHEbuffers = n_buffers;
- else
- vfp->nCACHEbuffers = DEFAULT_nCACHE_BUFFERs;
-
- vfp->CACHEblockN = (long *) malloc (vfp->nCACHEbuffers * sizeof(long));
- if (vfp->CACHEblockN == NULL) {
- FREEvfp (vfp);
- return NULL;
- }
-
- vfp->CACHEmodified = (long *) malloc (vfp->nCACHEbuffers * sizeof(long));
- if (vfp->CACHEmodified == NULL) {
- FREEvfp (vfp);
- return NULL;
- }
-
- vfp->CACHEaccessedAt = (long *) malloc (vfp->nCACHEbuffers * sizeof(long));
- if (vfp->CACHEaccessedAt == NULL) {
- FREEvfp (vfp);
- return NULL;
- }
-
- vfp->CACHEbuffers = (char **) malloc (vfp->nCACHEbuffers * sizeof(char *));
- if (vfp->CACHEbuffers == NULL) {
- FREEvfp (vfp);
- return NULL;
- }
-
- for (bufferN = 0; bufferN < vfp->nCACHEbuffers; bufferN++) {
- vfp->CACHEbuffers[bufferN] = NULL;
- }
-
- /******************************************************************************
- * open file in fixed length record mode
- ******************************************************************************/
-
- #if defined(vms)
- sprintf (mrs, "mrs=%d", nCACHE_BUFFER_BYTEs);
- sprintf (deq, "deq=%d", VMS_DEFAULT_nALLOCATION_BLOCKS);
- vfp->fp = fopen (file_spec, a_mode, "rfm=fix", mrs, deq);
- #endif
-
- #if defined(unix) | defined(__MSDOS__)
- vfp->fp = fopen (file_spec, a_mode);
- #endif
-
- if (vfp->fp == NULL) {
- FREEvfp (vfp);
- return NULL;
- }
-
- /******************************************************************************
- * determine length of file
- ******************************************************************************/
-
- status = fseek (vfp->fp, 0, SEEK_END);
- if (status == EOF) {
- fclose (vfp->fp);
- FREEvfp (vfp);
- return NULL;
- }
-
- vfp->eof = ftell (vfp->fp);
- if (vfp->eof == EOF) {
- fclose (vfp->fp);
- FREEvfp (vfp);
- return NULL;
- }
-
- vfp->PHYeof = vfp->eof;
-
- if (vfp->PHYeof == 0)
- vfp->PHYlastBlockN = -1;
- else
- vfp->PHYlastBlockN = (vfp->PHYeof - 1) / nCACHE_BUFFER_BYTEs;
-
- /******************************************************************************
- * initialize the rest of the V structure
- ******************************************************************************/
-
- if (strchr(a_mode,'a') == NULL)
- vfp->offset = 0;
- else
- vfp->offset = vfp->eof;
-
- vfp->error = FALSE;
- vfp->pseudoClock = 1;
-
- for (bufferN = 0; bufferN < vfp->nCACHEbuffers; bufferN++) {
- vfp->CACHEblockN[bufferN] = -1;
- vfp->CACHEmodified[bufferN] = FALSE;
- vfp->CACHEaccessedAt[bufferN] = -1;
- }
-
- vfp->lastBufferNaccessed = -1;
-
- /******************************************************************************
- * return pointer to V structure
- ******************************************************************************/
-
- return vfp;
- }
-
- /******************************************************************************
- * Vseek - seek to a position in the file.
- ******************************************************************************/
-
- int Vseek (vfp, offset, direction)
- VFILE *vfp; /* pointer to V structure */
- long offset; /* new read/write offset (position) */
- int direction; /* reference for offsetting */
- {
-
- if (vfp->magic_number != VIO_MAGIC_NUMBER) return EOF;
- if (vfp->error) return EOF;
-
- switch (direction) {
- case SEEK_SET: /* seek from beginning of file */
- if (offset >= 0) {
- vfp->offset = offset;
- return 0;
- }
- else
- return EOF;
-
- case SEEK_CUR: /* seek from current offset */
- if (vfp->offset + offset >= 0) {
- vfp->offset += offset;
- return 0;
- }
- else
- return EOF;
-
- case SEEK_END: /* seek to EOF */
- vfp->offset = vfp->eof;
- return 0;
- }
-
- return EOF; /* illegal seek */
- }
-
- /******************************************************************************
- * Vtell - return current offset (position) in file. This is the byte offset
- * one past the last byte written.
- ******************************************************************************/
-
- long Vtell (vfp)
- VFILE *vfp; /* pointer to V structure */
- {
- if (vfp->magic_number != VIO_MAGIC_NUMBER) return EOF;
- if (vfp->error) return EOF;
-
- return vfp->offset;
- }
-
- /******************************************************************************
- * Veof - check if at EOF. If so, return non-zero (TRUE). If not, return zero
- * (FALSE). This is different that the 'feof' function in that a read at
- * the EOF doesn't have to occur before 'veof' will return TRUE (change
- * to be like 'feof'?).
- ******************************************************************************/
-
- int Veof (vfp)
- VFILE *vfp; /* pointer to V structure */
- {
- if (vfp->magic_number != VIO_MAGIC_NUMBER) return FALSE;
- if (vfp->error) return FALSE;
-
- if (vfp->offset >= vfp->eof)
- return TRUE;
- else
- return FALSE;
- }
-
- /******************************************************************************
- * Vread - read from the file.
- ******************************************************************************/
-
- long Vread (buffer, item_size, n_items, vfp)
- void *buffer; /* pointer to buffer to read into */
- long item_size; /* size (in bytes) of each item to read */
- long n_items; /* number of items to read */
- VFILE *vfp; /* pointer to V structure */
- {
- long Nbytes; /* total number of bytes in read */
- long firstBlockN; /* first block involved in read */
- long lastBlockN; /* last block involved in read */
- long bufferOffset; /* offset (bytes) into buffer */
- long Xbytes; /* number of bytes in a transfer */
- long blockN; /* block number in file (from 0) */
- long bufferN; /* cache buffer number */
-
- if (vfp->magic_number != VIO_MAGIC_NUMBER) return 0;
- if (vfp->error) return 0; /* access not allowed after first error */
-
- Nbytes = item_size * n_items;
-
- if (Nbytes == 0) return 0;
- if (vfp->offset + Nbytes > vfp->eof) return 0; /* IMPROVE */
-
- firstBlockN = vfp->offset / nCACHE_BUFFER_BYTEs;
- lastBlockN = (vfp->offset + Nbytes - 1) / nCACHE_BUFFER_BYTEs;
-
- bufferOffset = vfp->offset % nCACHE_BUFFER_BYTEs;
- Xbytes = Minimum (Nbytes, (nCACHE_BUFFER_BYTEs - bufferOffset));
-
- CACHEbufferN (vfp, firstBlockN, bufferN);
- if (bufferN == -1) PAGEin (vfp, firstBlockN, bufferN, 0);
-
- memmove (buffer, (vfp->CACHEbuffers[bufferN] + bufferOffset), Xbytes);
- vfp->CACHEaccessedAt[bufferN] = vfp->pseudoClock++;
- vfp->lastBufferNaccessed = bufferN;
- buffer = (char *) buffer + Xbytes;
-
- for (blockN = firstBlockN + 1; blockN < lastBlockN; blockN++) {
- CACHEbufferN (vfp, blockN, bufferN);
- if (bufferN != -1) {
- memmove (buffer, vfp->CACHEbuffers[bufferN], nCACHE_BUFFER_BYTEs);
- vfp->CACHEaccessedAt[bufferN] = vfp->pseudoClock++;
- vfp->lastBufferNaccessed = bufferN;
- }
- else {
- READ ((nCACHE_BUFFER_BYTEs * blockN), buffer, nCACHE_BUFFER_BYTEs, 1,
- vfp, 0);
- }
- buffer = (char *) buffer + nCACHE_BUFFER_BYTEs;
- }
-
- if (lastBlockN != firstBlockN) {
- Xbytes = vfp->offset + Nbytes - (nCACHE_BUFFER_BYTEs * lastBlockN);
- CACHEbufferN (vfp, lastBlockN, bufferN);
- if (bufferN == -1) PAGEin (vfp, lastBlockN, bufferN, 0);
- memmove (buffer, vfp->CACHEbuffers[bufferN], Xbytes);
- vfp->CACHEaccessedAt[bufferN] = vfp->pseudoClock++;
- vfp->lastBufferNaccessed = bufferN;
- }
-
- vfp->offset += Nbytes;
-
- return n_items;
- }
-
- /******************************************************************************
- * Vwrite - write to the file.
- ******************************************************************************/
-
- long Vwrite (buffer, item_size, n_items, vfp)
- void *buffer; /* pointer to buffer to write from */
- long item_size; /* size (in bytes) of each item to write */
- long n_items; /* number of items to write */
- VFILE *vfp; /* pointer to V structure */
- {
- long Nbytes; /* total number of bytes in write */
- long firstBlockN; /* first block involved in write */
- long lastBlockN; /* last block involved in write */
- long bufferOffset; /* offset (bytes) into buffer */
- long blockN; /* block number in file (from 0) */
- long Xbytes; /* number of bytes in a transfer */
- long bufferN; /* cache buffer number */
-
- if (vfp->magic_number != VIO_MAGIC_NUMBER) return 0;
- if (vfp->error) return 0; /* access not allowed after first error */
-
- Nbytes = item_size * n_items;
-
- if (Nbytes == 0) return 0;
-
- firstBlockN = vfp->offset / nCACHE_BUFFER_BYTEs;
- lastBlockN = (vfp->offset + Nbytes - 1) / nCACHE_BUFFER_BYTEs;
-
- bufferOffset = vfp->offset % nCACHE_BUFFER_BYTEs;
- Xbytes = Minimum (Nbytes, (nCACHE_BUFFER_BYTEs - bufferOffset));
-
- CACHEbufferN (vfp, firstBlockN, bufferN);
- if (bufferN == -1)
- if (firstBlockN <= vfp->PHYlastBlockN) {
- PAGEin (vfp, firstBlockN, bufferN, 0);
- }
- else {
- if (ALLOCbuffer(vfp, &bufferN) == 0) return 0;
- vfp->CACHEblockN[bufferN] = firstBlockN;
- }
-
- memmove ((vfp->CACHEbuffers[bufferN] + bufferOffset), buffer, Xbytes);
- vfp->CACHEmodified[bufferN] = TRUE;
- vfp->CACHEaccessedAt[bufferN] = vfp->pseudoClock++;
- vfp->lastBufferNaccessed = bufferN;
-
- vfp->eof = Maximum (vfp->eof, (vfp->offset + Xbytes));
- buffer = (char *) buffer + Xbytes;
-
- for (blockN = firstBlockN + 1; blockN < lastBlockN; blockN++) {
- CACHEbufferN (vfp, blockN, bufferN);
- if (bufferN != -1) {
- memmove (vfp->CACHEbuffers[bufferN], buffer, nCACHE_BUFFER_BYTEs);
- vfp->CACHEmodified[bufferN] = TRUE;
- vfp->CACHEaccessedAt[bufferN] = vfp->pseudoClock++;
- vfp->lastBufferNaccessed = bufferN;
- }
- else {
- WRITEblock (vfp, blockN, buffer, nCACHE_BUFFER_BYTEs, 0);
- }
-
- vfp->eof = Maximum (vfp->eof,
- ((nCACHE_BUFFER_BYTEs * blockN) +
- nCACHE_BUFFER_BYTEs));
- buffer = (char *) buffer + nCACHE_BUFFER_BYTEs;
- }
-
- if (lastBlockN != firstBlockN) {
- Xbytes = vfp->offset + Nbytes - (nCACHE_BUFFER_BYTEs * lastBlockN);
-
- CACHEbufferN (vfp, lastBlockN, bufferN);
- if (bufferN == -1)
- if (lastBlockN <= vfp->PHYlastBlockN) {
- PAGEin (vfp, lastBlockN, bufferN, 0);
- }
- else {
- if (ALLOCbuffer(vfp, &bufferN) == 0) return 0;
- vfp->CACHEblockN[bufferN] = lastBlockN;
- }
-
- memmove (vfp->CACHEbuffers[bufferN], buffer, Xbytes);
- vfp->CACHEmodified[bufferN] = TRUE;
- vfp->CACHEaccessedAt[bufferN] = vfp->pseudoClock++;
- vfp->lastBufferNaccessed = bufferN;
-
- vfp->eof = Maximum (vfp->eof, ((nCACHE_BUFFER_BYTEs * lastBlockN) + Xbytes));
- }
-
- vfp->offset += Nbytes;
-
- return n_items;
- }
-
- /******************************************************************************
- * Vclose - close the file.
- ******************************************************************************/
-
- int Vclose (vfp)
- VFILE *vfp; /* pointer to V structure */
- {
- int status; /* status code from I/O function call */
- long bufferN; /* cache buffer number */
- long Nbytes; /* number of bytes to write */
-
- if (vfp->magic_number != VIO_MAGIC_NUMBER) return EOF;
-
- /******************************************************************************
- * write cache buffer (if no previous errors)
- ******************************************************************************/
-
- if ( ! vfp->error)
- for (bufferN = 0; bufferN < vfp->nCACHEbuffers; bufferN++)
- if (vfp->CACHEmodified[bufferN]) {
- #if defined(vms)
- Nbytes = nCACHE_BUFFER_BYTEs;
- #endif
- #if defined(unix) | defined(__MSDOS__)
- Nbytes = Minimum (nCACHE_BUFFER_BYTEs,
- (vfp->eof -
- nCACHE_BUFFER_BYTEs * vfp->CACHEblockN[bufferN]));
- #endif
- WRITEblock (vfp, vfp->CACHEblockN[bufferN], vfp->CACHEbuffers[bufferN],
- Nbytes, EOF);
- vfp->CACHEmodified[bufferN] = FALSE;
- }
-
- /******************************************************************************
- * close the file
- ******************************************************************************/
-
- status = fclose (vfp->fp);
-
- /******************************************************************************
- * deallocate V structure
- ******************************************************************************/
-
- FREEvfp (vfp);
-
- /******************************************************************************
- * return status of fclose call
- ******************************************************************************/
-
- return status;
- }
-